package com.xuebang.admin.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xuebang.admin.util.JsonUtil;
import com.xuebang.admin.web.Result;

@Controller
@RequestMapping("/db")
public class DbOperateController {

	private String StrHost = "113.11.196.135";
	private String strPort = "3306";
	private String strDatabase = "lykedu";
	private String strUserName = "myh";
	private String strPasswd = "xbsd809810";
	private String strDestUrlWd = "D:\\";
	private String strDestUrlLx = "/var/wwwroot/news/DBBak/";
	// 错误标志
	private int intFlag = 0;
	private StringBuilder sbLog = new StringBuilder();
	
	/**
	 * 备份(还原)页面
	 */
	@RequestMapping(value = "backup")
	public String backup() {
		return "/db/backup";
	}

	/**
	 * 备份操作开始
	 */
	@RequestMapping(value = "toBackup",method = RequestMethod.GET,produces = "text/plain;charset=UTF-8")
	public @ResponseBody
	String toBackup() {

		try {
			init();
			backupLinux();
			//backupWindows();
			if(intFlag==0) {
				return JsonUtil.dump(Result.success("数据库备份完成"));
			} else {
				StringBuilder sbTempLog = new StringBuilder(sbLog.toString());

				// 重置
				intFlag = 0;
				sbLog.setLength(0);
				return JsonUtil.dump(Result.error(sbTempLog));
			}
		} catch (Exception e) {
			e.printStackTrace();
			return JsonUtil.dump(Result.error(e.getMessage()));
		}
	}

	/**
	 * 备份
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
	private void backupWindows() throws IOException, InterruptedException{
		
		// 命令
		// 注：原本下面是直接写的mysqldump，发现产生的文件为空，从网上找到原因，说是由于安装路径中出现空格导致问题
		// 解决办法是把mysqldump拷出来，放置到一个位置，然后使用路径+mysqldump的方法，可以获得
		String strBackupCmd = "D:\\mysqldump  --host="+StrHost + " --port=" + strPort + " --user="+strUserName
			+" --password="+strPasswd + " --opt "+strDatabase+" > " +strDestUrlWd;

		Process p = Runtime.getRuntime().exec("cmd /c " +strBackupCmd); 
		// 从网上看到如果这期间出现错误，这里waitfor方法会被阻塞一直等待下去
		StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");              
        
	      // kick off stderr   
	      errorGobbler.start();  

	      //StreamGobbler outGobbler = new StreamGobbler(p.getInputStream(), "STDOUT");  
	      // kick off stdout 
	      //outGobbler.start(); 
	      
		p.waitFor();
		strDestUrlWd = "D:\\";
	}
	
	/**
	 * 备份之前的准备工作，包括从config文件中读取服务器地址,端口号，账号，密码
	 * 根据时分秒建立备份文件等。
	 */
	private void init(){
		
		// 本次省略从config文件中读取服务器地址,端口号，账号，密码
		// 建立文件
		SimpleDateFormat sdf = new SimpleDateFormat("yyyMMddHHmmss");
		String strDate = sdf.format(new Date());
		strDestUrlLx = strDestUrlLx + strDate +".sql";
		strDestUrlWd = strDestUrlWd + strDate +".sql";
	}
	
	/**
	 * 备份
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
	private void backupLinux() throws IOException, InterruptedException{
		
		// 命令
		String strBackupCmd = "/usr/local/mysql/bin/mysqldump --host="+StrHost + " --port=" + strPort + " --user="+strUserName
			+" --password="+strPasswd + " --opt "+strDatabase+" > " +strDestUrlLx;

		Process p = Runtime.getRuntime().exec(new String[] { "sh", "-c", strBackupCmd });
		// 从网上看到如果这期间出现错误，这里waitfor方法会被阻塞一直等待下去
		StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");              
        
	      // kick off stderr   
	      errorGobbler.start();  

	      //StreamGobbler outGobbler = new StreamGobbler(p.getInputStream(), "STDOUT");  
	      // kick off stdout 
	      //outGobbler.start(); 
	      
		p.waitFor();
		
		strDestUrlLx = "/var/wwwroot/news/DBBak/";
	}
	
	/** 
	 * 用于处理Runtime.getRuntime().exec产生的错误流及输出流 
	 * 
	 */ 
	class  StreamGobbler extends Thread{

		InputStream is;
	    String type;
	    OutputStream os;  
	          
	    StreamGobbler(InputStream is, String type) {  
	        this(is, type, null);  
	    }  
	  
	    StreamGobbler(InputStream is, String type, OutputStream redirect) {  
	        this.is = is;  
	        this.type = type;  
	        this.os = redirect;  
	    }  
	      
	    public void run() {  
	        InputStreamReader isr = null;  
	        BufferedReader br = null;  
	        PrintWriter pw = null;  
	        try {  
	            if (os != null)  
	                pw = new PrintWriter(os);  
	                  
	            isr = new InputStreamReader(is);  
	            br = new BufferedReader(isr);  
	            String line=null;  
	            while ( (line = br.readLine()) != null) {  
	                //if (pw != null){
	                    //pw.println(line);
	                	if(type.equalsIgnoreCase("error")){
	                		intFlag = 1;
	                		sbLog.append(line);
	                	}
	               // }
	            }  
	              
//	            if (pw != null)  
//	                pw.flush();  
	        } catch (IOException ioe) {  
	            ioe.printStackTrace();    
	        } finally{  
	            if(pw!=null){
	            	pw.close();
	            }  
	            if(br!=null){
	            	try {
						br.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            }
	            if(isr!=null){
	            	try {
						isr.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            }
	        }  
	    }  
	}  
}
